﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Spring.Data.NHibernate.Generic.Support;
using NHibernate;
using System.Data.SqlClient;
using System.Diagnostics;
using NHibernate.Linq;
namespace MYSMRM.Dao.Base
{
    public abstract class DaoBase<T> : HibernateDaoSupport, IDao<T> where T : class
    {
        public virtual object Save(T entity)
        {
            return this.HibernateTemplate.Save(entity);
        }

        public virtual T Get(object id)
        {
            return this.HibernateTemplate.Get<T>(id);
        }

        public virtual T Load(object id)
        {
            return this.HibernateTemplate.Load<T>(id);
        }

        public virtual IQueryable<T> LoadAll()
        {
            var result = Session.Query<T>();
            return result;
        }

        public virtual void Update(T entity)
        {
            this.HibernateTemplate.Update(entity);
        }

        public virtual void Delete(object id)
        {
            var entity = this.HibernateTemplate.Get<T>(id);
            if (entity == null)
            {
                return;
            }

            this.HibernateTemplate.Delete(entity);
        }

        public virtual IQueryable<T> LoadAllWithPage(out long count, int pageIndex, int pageSize)
        {
            var result = Session.Query<T>();
            count = result.LongCount();

            return result.Skip((pageIndex - 1) * pageSize).Take(pageSize);
        }


        public virtual void Delete(IList<object> idList)
        {
            foreach (var item in idList)
            {
                var entity = this.HibernateTemplate.Get<T>(item);
                if (entity == null)
                {
                    return;
                }

                this.HibernateTemplate.Delete(entity);
            }
        }

        public virtual void SaveOrUpdate(T entity)
        {
            this.HibernateTemplate.SaveOrUpdate(entity);
        }

        /// <summary>
        /// 执行ExecuteNonQuery
        /// </summary>
        /// <param name="sql"></param>
        public virtual void ExecuteNonQuery(string sql)
        {
            ITransaction transaction = null;
            try
            {
                transaction = Session.BeginTransaction();
                IDbCommand command = Session.Connection.CreateCommand();
                transaction.Enlist(command);//注意此处要把command添加到事物中
                command.CommandText = sql;
                command.ExecuteNonQuery();
                transaction.Commit();
            }
            catch (Exception ex)
            {
                if (transaction != null)
                {
                    transaction.Rollback();
                }
                throw ex;
            }
        }

        /// <summary>
        /// 填充DataSet
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        //public virtual DataSet ExecuteDataset(string sql, bool t)
        //{
        //    DataSet ds = new DataSet();
        //    try
        //    {
        //        IDbCommand command = Session.Connection.CreateCommand();
        //        command.CommandText = sql;

        //        IDataReader reader = command.ExecuteReader();
        //        DataTable result = new DataTable();
        //        //result.Load(reader);//此方法亦可
        //        DataTable schemaTable = reader.GetSchemaTable();
        //        for (int i = 0; i < schemaTable.Rows.Count; i++)
        //        {
        //            string columnName = schemaTable.Rows[i][0].ToString();
        //            result.Columns.Add(columnName);
        //        }
        //        while (reader.Read())
        //        {
        //            int fieldCount = reader.FieldCount;
        //            object[] values = new Object[fieldCount];
        //            for (int i = 0; i < fieldCount; i++)
        //            {
        //                values[i] = reader.GetValue(i);
        //            }
        //            result.Rows.Add(values);
        //        }
        //        ds.Tables.Add(result);
        //    }
        //    catch (Exception ex)
        //    {
        //        Debug.Assert(false);
        //    }

        //    return ds;
        //}

        /// <summary>
        /// 填充DataSet（此方法亦可）
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual DataSet ExecuteDataSet(string sql)
        {
            DataSet ds = new DataSet();
            try
            {
                IDbCommand command = Session.Connection.CreateCommand();
                command.CommandText = sql;
                SqlDataAdapter da = new SqlDataAdapter(command as SqlCommand);
                da.Fill(ds);
            }
            catch (Exception ex)
            {
                Debug.Assert(false);
            }

            return ds;
        }

        public virtual DataTable ExecuteDataTable(string sql)
        {
            DataTable result = new DataTable();
            try
            {
                IDbCommand command = Session.Connection.CreateCommand();
                command.CommandText = sql;
                IDbConnection conn = Session.Connection;

                //tran = Session.BeginTransaction();
                //tran.Enlist(command);

                command.Connection = conn;
                if (Session.Transaction != null)
                    Session.Transaction.Enlist(command);

                // Method 1
                SqlDataAdapter da = new SqlDataAdapter((SqlCommand)command);
                DataSet ds = new DataSet();
                da.Fill(ds);
                if (ds.Tables[0] != null)
                    //table = ds.Tables[0].Copy(); 
                    result = ds.Tables[0];


                // Method 2
                //IDataReader reader = command.ExecuteReader();

                //result.Load(reader);//此方法亦可
                //DataTable schemaTable = reader.GetSchemaTable();
                //for (int i = 0; i < schemaTable.Rows.Count; i++)
                //{
                //    string columnName = schemaTable.Rows[i][0].ToString();
                //    result.Columns.Add(columnName);
                //}
                //while (reader.Read())
                //{
                //    int fieldCount = reader.FieldCount;
                //    object[] values = new Object[fieldCount];
                //    for (int i = 0; i < fieldCount; i++)
                //    {
                //        values[i] = reader.GetValue(i);
                //    }
                //    result.Rows.Add(values);
                //}

                //tran.Commit();
                //tran.Dispose();
                //reader.Dispose();
                command.Dispose();
            }
            catch (Exception ex)
            {
                //if (tran != null)
                //{
                //    tran.Rollback();
                //}
                Debug.Assert(false);
            }

            return result;
        }

        public static DataTable ExecuteDataTable(ISession dbSession, string queryString, string tablename)
        {
            System.Data.DataTable dt = ExecuteDataTable(dbSession, queryString);

            if (dt != null)
                dt.TableName = tablename;

            return dt;
        }

        public static DataTable ExecuteDataTable(ISession dbSession, string queryString)
        {
            DataTable table = null;
            IDbCommand cmd = new SqlCommand();
            //#if (SQLServer)
            //            cmd = new SqlCommand();// dbSession.SessionFactory.ConnectionProvider.Driver.GenerateCommand(CommandType.Text, (global::NHibernate.SqlCommand.SqlString)queryString, (global::NHibernate.SqlTypes.SqlType[])null);
            //#else
            //            cmd = new System.Data.OracleClient.OracleCommand();
            //#endif

            cmd.CommandText = queryString;
            IDbConnection conn = dbSession.Connection;

            cmd.Connection = conn;
            if (dbSession.Transaction != null)
                dbSession.Transaction.Enlist(cmd);

            if (cmd.GetType() == typeof(SqlCommand))
            {
                SqlDataAdapter da = new SqlDataAdapter((SqlCommand)cmd);
                //#if (SQLServer)
                //                da = new SqlDataAdapter((SqlCommand)cmd);
                //#else
                //                da = new System.Data.OracleClient.OracleDataAdapter((SqlCommand)cmd);
                //#endif

                DataSet ds = new DataSet();
                da.Fill(ds);
                if (ds.Tables[0] != null)
                    //table = ds.Tables[0].Copy(); 
                    table = ds.Tables[0];
            }
            return table;
        }
    }
}
